"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

from graphene_django import DjangoObjectType
from django.utils.translation import gettext_lazy as _, ngettext_lazy
from django.apps import apps
from siriuso.api.mixins import SiriusoAuthNode
from siriuso.api.filters import SiriusoFilterConnectionField
from siriuso.utils import get_enhavo, get_lang_kodo, lingvo_kodo_normaligo
from graphene.types import Union
from graphene import List, Int, Field, ObjectType, relay
from uzantoj.api.schema import UzantoNode
from muroj.api.schema import (MurojUzantoEnskriboNode, MuroEnskriboNode, MurojUzantoEnskriboKomentoNode,
                              MuroEnskriboKomentoNode)
from konferencoj.api.schema import KonferencojTemoKomentoNode, KonferencojTemoNode
from premioj.api.schema import PremiojKondichoNode
from tamagocxi.api.schema import TamagocxiKondichoNode
from mesagxilo.api.schema import MesagxiloBabilejoNode
from ..models import UzantojSciigoj


class SciigajObjektoj(Union):
    class Meta:
        types = (UzantoNode, MurojUzantoEnskriboNode, MuroEnskriboNode, MurojUzantoEnskriboKomentoNode,
                 MuroEnskriboKomentoNode, KonferencojTemoKomentoNode, KonferencojTemoNode, PremiojKondichoNode,
                 MesagxiloBabilejoNode, TamagocxiKondichoNode)


class UzantoSciigoNode(SiriusoAuthNode, DjangoObjectType):
    objektoj = List(SciigajObjektoj)

    class Meta:
        model = UzantojSciigoj
        filter_fields = {
            'uuid': ['exact'],
            'forigo': ['exact'],
            'arkivo': ['exact'],
            'publikigo': ['exact'],
            'krea_dato': ['exact', 'lte', 'gte', 'lt', 'gt'],
            'vidita': ['exact'],
            'leganta_dato': ['exact', 'lte', 'gte', 'lt', 'gte'],
        }
        exclude = ('atributoj',)
        interfaces = (relay.Node,)

    def resolve_teksto(self, info):
        parametroj = None

        if self.atributoj and 'teksto_parametroj' in self.atributoj:
            parametroj = dict()
            modeloj = dict()
            objektoj = dict()

            for par, val in self.atributoj.get('teksto_parametroj').items():
                if isinstance(val, dict):
                    if val.get('model') not in modeloj:
                        model = apps.get_model(val.get('model'))
                        modeloj[val.get('model')] = model
                    else:
                        model = modeloj.get(val.get('model'))

                    if val.get('model') in objektoj and val.get('pk') in objektoj[val.get('model')]:
                        objekto = objektoj[val.get('model')][val.get('pk')]
                    else:
                        try:
                            objekto = model.objects.get(pk=val.get('pk'))

                            if val.get('model') in objektoj:
                                objektoj[val.get('model')][val.get('pk')] = objekto
                            else:
                                objektoj[val.get('model')] = {val.get('pk'): objekto}
                        except model.DoesNotExist:
                            parametroj[par] = None
                            continue

                    nova_val = getattr(objekto, val.get('field'))

                    if isinstance(nova_val, dict):
                        nova_val = get_enhavo(
                            nova_val, lingvo=lingvo_kodo_normaligo(get_lang_kodo(info.context)),
                            empty_values=True
                        )[0]

                    parametroj[par] = nova_val
                else:
                    parametroj[par] = val

        if self.atributoj and 'pluralo' in self.atributoj:
            pluralo = self.atributoj.get('pluralo')
            cnt = next(iter(parametroj.items()))[1]
            return ngettext_lazy(self.teksto, pluralo, cnt) % parametroj

        return _(self.teksto) % parametroj if parametroj else _(self.teksto)

    def resolve_objektoj(self, info):
        if self.atributoj and 'objektoj' in self.atributoj:
            objektoj = list()
            obj_models = dict()

            for obj in self.atributoj['objektoj']:
                model_fullname = obj['model']
                app_label, model_name = model_fullname.split('.')

                if model_fullname not in obj_models:
                    obj_models.update({
                        model_fullname: apps.get_model(app_label, model_name)
                    })

                model = obj_models[model_fullname]

                try:
                    objektoj.append(model.objects.get(pk=obj['pk']))
                except model.DoesNotExist:
                    pass

            return objektoj

        return None


class UzantojSciigojQuery(ObjectType):
    tuta = Int()
    ne_vidata = Int()
    sciigoj = SiriusoFilterConnectionField(UzantoSciigoNode)

    @staticmethod
    def resolve_tuta(root, info):
        user = info.context.user

        if user.is_authenticated:
            return UzantojSciigoj.objects.filter(posedanto=user, forigo=False, arkivo=False, publikigo=True).count()

        return 0

    @staticmethod
    def resolve_ne_vidata(root, info):
        user = info.context.user

        if user.is_authenticated:
            return UzantojSciigoj.objects.filter(
                posedanto=user, forigo=False, arkivo=False, publikigo=True, vidita=False
            ).count()

        return 0

    @staticmethod
    def resolve_sciigoj(root, info, **kwargs):
        user = info.context.user

        if user.is_authenticated:
            return UzantojSciigoj.objects.filter(posedanto=user, forigo=False, arkivo=False, publikigo=True)

        return UzantojSciigoj.objects.none()


class SciigojQuery(ObjectType):
    uzantoj_sciigoj = Field(UzantojSciigojQuery)

    @staticmethod
    def resolve_uzantoj_sciigoj(root, info):
        return UzantojSciigojQuery()
